home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / db / esm-3.1 / esm-3 / usr / local / sm / src / serverlib / msg / loop.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-05  |  7.8 KB  |  326 lines

  1. /*
  2.  *   $RCSfile: loop.C,v $  
  3.  *   $Revision: 1.1.1.1 $  
  4.  *   $Date: 1996/05/04 21:55:54 $      
  5.  */ 
  6. /**********************************************************************
  7. * EXODUS Database Toolkit Software
  8. * Copyright (c) 1991 Computer Sciences Department, University of
  9. *                    Wisconsin -- Madison
  10. * All Rights Reserved.
  11. *
  12. * Permission to use, copy, modify and distribute this software and its
  13. * documentation is hereby granted, provided that both the copyright
  14. * notice and this permission notice appear in all copies of the
  15. * software, derivative works or modified versions, and any portions
  16. * thereof, and that both notices appear in supporting documentation.
  17. *
  18. * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
  19. * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.  
  20. * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  21. * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  22. *
  23. * The EXODUS Project Group requests users of this software to return 
  24. * any improvements or extensions that they make to:
  25. *
  26. *   EXODUS Project Group 
  27. *     c/o David J. DeWitt and Michael J. Carey
  28. *   Computer Sciences Department
  29. *   University of Wisconsin -- Madison
  30. *   Madison, WI 53706
  31. *
  32. *     or exodus@cs.wisc.edu
  33. *
  34. * In addition, the EXODUS Project Group requests that users grant the 
  35. * Computer Sciences Department rights to redistribute these changes.
  36. **********************************************************************/
  37. #include "sysdefs.h"
  38. #include "ess.h"
  39. #include "checking.h"
  40. #include "trace.h"
  41. #include "error.h"
  42. #include "list.h"
  43. #include "tid.h"
  44. #include "io.h"
  45. #include "lock.h"
  46. #include "object.h"
  47. #include "msgdefs.h"
  48. #include "thread.h"
  49. #include "semaphore.h"
  50. #include "latch.h"
  51. #include "link.h"
  52. #include "host.h"
  53. #include "bitvec.h"
  54. #include "bf.h"
  55. #include "disk.h"
  56. #include "volume.h"
  57. #include "threadstate.h"
  58. #include "msgvector.h"
  59. #include "msg_funcs.h"
  60. #include "timer.h"
  61. #include "thread_funcs.h"
  62. #include "disk_funcs.h"
  63. #include "server_util_funcs.h"
  64. #include "mr_extfuncs.h"
  65. #include "thread_globals.h"
  66. #include "msg_globals.h"
  67. #include "recover_globals.h"
  68. #include "stat_globals.h"
  69. #include "queue_consist.h"
  70.  
  71.  void
  72. loop ()
  73.  
  74. {
  75.     static    TIMEVAL    *ZeroTime = (TIMEVAL *)0;
  76.     SELECTTIME        SelectTimeStruct;
  77.  
  78.     register LINK    *link;
  79.     register TCB    *tcb;
  80.     static     int        numReady = 0;
  81.     register int    readyIndex;
  82.  
  83.  
  84.     Active->state = THREAD_LOOP;
  85.  
  86.     for (;;)    {
  87. #        ifdef DEBUG
  88.         checkMalloc();
  89. #        endif DEBUG
  90.  
  91.         TRPRINT(TR_THREAD, TR_LEVEL_2, ("in loop thread:%d", Active->id));
  92.         SelectTime = ZeroTime; /* block indefinitely */
  93. #ifdef DEBUG
  94.         loops++;
  95. #endif DEBUG
  96.  
  97.  
  98.         /*
  99.          *    check to see if we are down to the last thread
  100.          */
  101.         if (Spare == NULL)    {
  102. #ifdef DEBUG
  103.             loop_spare++;
  104. #endif DEBUG
  105.  
  106.             /*
  107.              *    this will be made the spare thread
  108.              */
  109.             TRPRINT(TR_THREAD, TR_LEVEL_2, ("returning:%d the spare thread", Active->id));
  110.             SelectMask = AllMask;
  111.             SelectRestrict = 0;
  112.             Spare = Active;
  113.             dispatch(THREAD_SPARE_TCB);
  114.  
  115.         } else {
  116.  
  117.             /*
  118.              *    check to see if there is a thread ready to run
  119.              */
  120.             if ((tcb = (TCB *) listDeq( &ReadyList )) != NULL)    {
  121.  
  122.                 TRPRINT(TR_THREAD, TR_LEVEL_2, ("thread:%d off ready list", tcb->id));    
  123.  
  124. #ifdef DEBUG
  125.                 loop_ran_ready++;
  126. #endif DEBUG
  127.                 /*
  128.                  *    switch to that thread
  129.                  */
  130.                 freeThread(Active);
  131.                 threadSwitch(tcb);
  132.                 threadRestart();
  133.             }
  134.         }
  135.  
  136.         /* 
  137.          * Check all the disk queues for potential work.
  138.          */
  139.         if( selectDisk() ) 
  140.             continue;
  141.  
  142.         /* 
  143.          * selectDisk() found nothing in the queues, so do a select.
  144.          */
  145.  
  146. select_again:
  147.         if(numReady == 0) {
  148.             /* 
  149.              * We have no ready fds. Get a new list (mask)
  150.              * of them by doing select again.
  151.              */
  152.             serv_sleeps++;
  153.             ReadMask = SelectMask;
  154.             
  155.             AwakenedAThread = FALSE;
  156.             /*
  157.              * Tick might call WakeUp, which puts a thread
  158.              * back on the ready queue.  We'd like that thread
  159.              * to get a chance to run before we do the next
  160.              * select
  161.              */
  162.             if((SelectTimeStruct.tv_sec = ServerTimer.Tick(FALSE, TRUE)) == 0){
  163.                 SelectTime = ZeroTime;
  164.             } else {
  165.                 SelectTime = &SelectTimeStruct;
  166.                 SelectTimeStruct.tv_usec = 0;
  167.             }
  168.             if(AwakenedAThread) {
  169.                 continue; /* for loop */
  170.             }
  171.  
  172.             TRPRINT(TR_MSG|TR_DISK, TR_LEVEL_2, 
  173.                     ("thread:%d %s on select", Active->id,
  174.                     ((SelectTime==ZeroTime)? "blocking indefinitely":
  175.                      (SelectTime == &SelectTimeStruct)? "blocking w/ timeout":
  176.                      "polling")));
  177.                      /* polling might not be used anymore, but the
  178.                       * code for tracing it is kept here anyway
  179.                       */
  180. #ifdef hpux
  181.             numReady = select(SelectBits, (int*)&ReadMask, 
  182. #else
  183.             numReady = select(SelectBits, (fd_set*)&ReadMask, 
  184. #endif
  185.                     NULL, NULL, SelectTime);
  186.         }
  187.         if(numReady<0) {
  188.             /*
  189.              *    See if the error was caused by an interupted select.
  190.              */
  191.             if (errno == EINTR) {
  192.                 /* Just try the select again */
  193.                 serv_sel_intrs++;
  194.  
  195.                 numReady = 0;
  196.                 TRPRINT(TR_MSG|TR_DISK, TR_LEVEL_1, 
  197.                     ("select interrupted: restart"));
  198.                 goto select_again;
  199.             } else {
  200.                 SM_ERROR(TYPE_FATAL, errno);
  201.             }
  202.         }
  203.         SM_ASSERT(LEVEL_1, Replies->willBlock == 1);
  204.         Replies->willBlock = 0;
  205.  
  206.         TRPRINT(TR_MSG|TR_DISK, TR_LEVEL_1, 
  207.             ("returned from select %d sockets ready, ReadMask 0x%x", 
  208.             numReady, ReadMask));
  209.  
  210.         /* 
  211.          * If numReady  is zero right away,
  212.          * we did a poll (or timeout) instead of an indefinite select, and
  213.          * nothing's ready to go, so check the queues again.
  214.          */
  215.         if(numReady == 0) {
  216.             continue; /* for loop */
  217.         }
  218.  
  219.         /*
  220.          * OK, now numReady > 0. 
  221.          *    do a round-robin through the ready fd mask,
  222.          *  giving priority to disk fds.
  223.          */
  224.         readyIndex = selectReceive( &ReadMask );
  225.  
  226.         TRPRINT(TR_MSG|TR_DISK, TR_LEVEL_1, 
  227.             ("socket fd=%d ready", readyIndex));
  228.  
  229.         /*
  230.          * remove this link from the read mask so that 
  231.          * we will not visit it until we do another select.
  232.          */
  233.         numReady--;
  234.         bic( &ReadMask, readyIndex );
  235.  
  236.         /*
  237.          *    switch based on the type of link
  238.          */
  239.         link = &(Links[readyIndex]);
  240. #ifdef DEBUG
  241.         if(link->id != readyIndex) {
  242.             fprintf(sm_ErrorStream, "LINK ID=%d, readyIndex %d / 0x%x\n",
  243.                 link->id, readyIndex, readyIndex);
  244.         }
  245.         SM_ASSERT(LEVEL_1, (link->id == readyIndex));
  246. #endif
  247.         TRPRINT(TR_CL|TR_MSG , TR_LEVEL_1, 
  248.         (" link type(%d) for fd=%d\n", link->linkClass, link->id ));
  249.         switch (link->linkClass)    {
  250.             case CL_DGRAM:
  251.                 sel_dgrams++;
  252.  
  253.                 TRPRINT(TR_MSG, TR_LEVEL_2, ("dgrams"));
  254.                 serverReceive(link); 
  255.                 break;
  256.  
  257.             case CL_CONNECT:
  258.                 sel_connects++;
  259.  
  260.                 TRPRINT(TR_MSG, TR_LEVEL_2, ("connect"));
  261.                 clientConnect(link);
  262.                 break;
  263.  
  264.             case CL_DISK:
  265.                 sel_disks++;
  266.  
  267.                 TRPRINT(TR_MSG, TR_LEVEL_2, ("disk"));
  268.                 diskReceive(link);
  269.                 break;
  270.  
  271.             case CL_TIMEDOUT:
  272.                 sel_clients++;
  273.                 TRPRINT(TR_MSG, TR_LEVEL_2, ("timed-out-client"));
  274.                 /* already freed the client link so just continue
  275.                  * the loop (same as doing a threadRestart)
  276.                  */
  277.                 link->linkClass = CL_UNUSED;
  278.                 TRPRINT(TR_MSG, TR_LEVEL_1, 
  279.                     ("link:%d is now type %d", link->id, link->linkClass));
  280.                 break;
  281.  
  282.             case CL_CLIENT:
  283.                 sel_clients++;
  284.  
  285.                 TRPRINT(TR_MSG, TR_LEVEL_2, ("client"));
  286.                 clientReceive(link);
  287.                 break;
  288.  
  289. #ifdef MEDIA_RECOVERY
  290.             case CL_MEDIA_RECOVERY:
  291.                 sel_media++;
  292.                 SM_ASSERT(LEVEL_1, MediaRecovery);
  293.                 mr_Receive(link);
  294.                 break;
  295. #endif MEDIA_RECOVERY
  296.  
  297.             case CL_STDOUT:
  298.             case CL_STDERR:
  299.                 /* like clearLink, but don't close the file */
  300.                 bic( &(SelectMask), link->id);
  301.                 bic( &(AllMask), link->id);
  302.                 break;
  303.  
  304.             case CL_STDIN:
  305.                 sel_stdin++;
  306. #ifdef MEDIA_RECOVERY
  307.                 mr_Receive(link);
  308. #else MEDIA_RECOVERY
  309.                 terminal_input(link);
  310. #endif MEDIA_RECOVERY
  311.                 break;
  312.  
  313.  
  314.             default:
  315.                 fprintf(sm_ErrorStream, "Unknown link type(%d) for fd=%d\n", 
  316.                         link->linkClass, link->id );
  317. #ifdef DEBUG
  318.                 /* grot TODO : remove */
  319.                 fprintf(sm_ErrorStream, "was %d\n", link->address.sin_family);
  320. #endif DEBUG
  321.                 SM_ERROR(TYPE_FATAL, esmINTERNAL);
  322.                 break;
  323.         } /* switch */
  324.     } /* for */
  325. }
  326.